<?php
/**
 * | ---------------------------------------------------------------------------------------------------
 * | Author：johnxu <fsyzxz@163.com>.
 * | ---------------------------------------------------------------------------------------------------
 * | Home: https://www.johnxu.net.
 * | ---------------------------------------------------------------------------------------------------
 * | Data: 2019/1/1
 * | ---------------------------------------------------------------------------------------------------
 * | Desc: Http服务
 * | ---------------------------------------------------------------------------------------------------
 */

class HttpServer
{
    const HOST = '0.0.0.0';
    const PORT = 8888;

    const CONFIG
        = array(
            'log_level'             => 1,
            'enable_static_handler' => true,
            'document_root'         => '/home/wwwroot/johnxu.swoole.local.cn/thinkphp/public/static',
            'worker_num'            => 4,
            'task_worker_num'       => 4, // 要开启任务，必须填写
        );

    /**
     * @var \Swoole\Http\Server
     */
    private $server;

    public function __construct()
    {
        $this->server = new \Swoole\Http\Server( self::HOST, self::PORT );
        $this->server->set( self::CONFIG );

        $this->server->on( 'WorkerStart', array( $this, 'onWorkerStart' ) );
        $this->server->on( 'request', array( $this, 'onRequest' ) );
        $this->server->on( 'task', array( $this, 'onTask' ) );
        $this->server->on( 'finish', array( $this, 'onFinish' ) );

        $this->server->start();
    }

    /**
     * 启动监听
     *
     * @param \Swoole\Http\Server $server
     * @param int                 $worker_id
     */
    public function onWorkerStart( \Swoole\Http\Server $server, int $worker_id )
    {
        // 定义application目录
        define( 'APP_PATH', __DIR__ . '/../application/' );
        // 加载thinkphp系统文件
        require __DIR__ . '/../thinkphp/base.php';
    }

    /**
     * 每次请求监听
     *
     * @param \Swoole\Http\Request  $request
     * @param \Swoole\Http\Response $response
     */
    public function onRequest( \Swoole\Http\Request $request, \Swoole\Http\Response $response )
    {
        // 定义application目录
        /*if ( !defined( 'APP_PATH' ) )
        {
            define( 'APP_PATH', __DIR__ . '/../application/' );
        }*/
        // 加载thinkphp系统文件
        // require_once __DIR__ . '/../thinkphp/base.php';

        $_SERVER            = $_GET = $_POST = [];
        $_SERVER['argv'][0] = '';
        if ( isset( $request->server ) )
        {
            foreach ( $request->server as $key => $item )
            {
                $_SERVER[strtoupper( $key )] = $item;
            }
        }

        if ( isset( $request->header ) )
        {
            foreach ( $request->server as $key => $item )
            {
                $_SERVER[strtoupper( $key )] = $item;
            }
        }

        if ( isset( $request->get ) )
        {
            foreach ( $request->get as $key => $item )
            {
                $_GET[$key] = $item;
            }
        }

        if ( isset( $request->post ) )
        {
            foreach ( $request->post as $key => $item )
            {
                $_POST[$key] = $item;
            }
        }
        $_POST['http_server'] = $this->server;
        // 可能需要注释Request.php 中path和pathinfo方法中的is_null($this->>pathinfo)
        ob_start();
        try
        {
            \think\Container::get( 'app', [ APP_PATH ] )->run()->send();
        }
        catch ( \Exception $e )
        {
            // $result = $e->getMessage();
        }
        $result = ob_get_contents();
        ob_end_clean();
        $response->end( $result );
    }

    /**
     * 任务监听
     *
     * @param swoole_server       $server
     * @param int                 $task_id
     * @param int                 $src_worker_id
     * @param                     $data
     *
     * @return string
     * @throws Exception
     */
    public function onTask( swoole_server $server, int $task_id, int $src_worker_id, $data )
    {
        $controller = isset( $data['controller'] ) ? '\\app\\common\\task\\' . ucfirst( $data['controller'] ) : '\\app\\common\\task\\Task';
        $obj        = new $controller();
        $method     = $data['method'] ?? '';
        if ( $method && method_exists( $obj, $method ) )
        {
            $flag = $obj->$method( $data['data'] );
        }
        else
        {
            // throw new \Exception( 'Not Found Method: ' . $method );
            return false;
        }

        return $flag;
    }

    /**
     * 任务执行完成
     *
     * @param \Swoole\Http\Server $server
     * @param int                 $task_id
     * @param                     $data
     */
    public function onFinish( \Swoole\Http\Server $server, int $task_id, $data )
    {
        echo 'finished - task' . PHP_EOL;
    }
}

new HttpServer();
